package com.joysuch.wwyt.workflow.api.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.joysuch.wwyt.app.bean.AppPendingTaskDto;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.workflow.api.service.NewProcessService;
import com.joysuch.wwyt.workflow.bean.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class NewProcessServiceImpl implements NewProcessService {

    @Autowired
    private RestTemplate restTemplate;

    @Resource
    private BaseConfigService baseConfigService;

    @Override
    public HttpHeaders getHeaders() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("user-id", "" + Context.getCurrentUser().getRealUserId());
        httpHeaders.set("user-name", "" + Context.getCurrentUser().getRealName());
        httpHeaders.set("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
        httpHeaders.set("app-id", "mvAmIwYJ7x6y0EADQvUb");
        httpHeaders.set("tenant-id", Context.getCurrentTenantId() + "");
        httpHeaders.set("org-code", Context.getCompanyCode());
        httpHeaders.set("signature", "30ca19ac3d133b30b9243ed61646136f7818a3d85e6a70a3bfaa68d3d64566c3");

        return httpHeaders;
    }

    public HttpHeaders getHeaders(BaseUser user) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("user-id", "" + user.getId());
        httpHeaders.set("user-name", "" + user.getRealName());
        httpHeaders.set("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
        httpHeaders.set("app-id", "mvAmIwYJ7x6y0EADQvUb");
        httpHeaders.set("tenant-id", user.getTenentId() + "");
        httpHeaders.set("org-code", user.getOrgCode());
        httpHeaders.set("signature", "30ca19ac3d133b30b9243ed61646136f7818a3d85e6a70a3bfaa68d3d64566c3");

        return httpHeaders;
    }
    @Override
    public List<AppPendingTaskDto> todoList() {
        TodoListResultBean result = queryTodoListFormNewProcessPlatform();

        List<AppPendingTaskDto> taskDtoList = Lists.newArrayList();
        if (result == null || result.getData() == null || result.getData().getRecords() == null) {
            log.info("query todoList error {}", result);
            return taskDtoList;
        }

        result.getData().getRecords().forEach(record -> {
            AppPendingTaskDto dto = new AppPendingTaskDto();
            dto.setProcessVersion(1);

            LocalDateTime localDateTime = DateTimeUtil.date2LocalDateTime(record.getCreateTime());
            dto.setLocalDateTime(localDateTime);
            //发起人
            dto.setCreateByName(record.getStartUsername());
            dto.setTaskName(record.getProcessDefinitionName());
            dto.setShowFirst(record.getTaskName());
            dto.setProcessInstanceId(record.getProcessInstanceId());
            dto.setProcessDefinitionKey(record.getProcessDefinitionKey());
            dto.setProcessDefinitionId(record.getProcessDefinitionId());
            dto.setNewProcessTaskId(record.getTaskId());
            dto.setModelMode(record.getModelMode());
            dto.setTodoListFields(record.getTodoListFields());
            Map<String, Object> variables = record.getVariables();
            if (variables != null) {
                Object serialNumber = variables.get("serialNumber");
                if (serialNumber != null) {
                    //作业类型编码
                    dto.setShowSecond((String) serialNumber);
                }
                if (StringUtils.isEmpty(dto.getCreateByName())) {
                    Object applyUserName = variables.get("applyUserName");
                    if (applyUserName != null) {
                        dto.setCreateByName((String) applyUserName);
                    }
                }
                dto.setVariables(record.getVariables());
            } else {
                dto.setVariables(Maps.newHashMap());
            }
            //流程名称
//            dto.setShowFirst(record.getProcessDefinitionName());

            //发起人
            dto.setShowThird(record.getStartUsername());

            taskDtoList.add(dto);
        });
        return taskDtoList;
    }

    private TodoListResultBean queryTodoListFormNewProcessPlatform() {
        HttpHeaders headers = getHeaders();
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();

        ResponseEntity<TodoListResultBean> exchange = null;
        try {
            exchange = restTemplate.exchange(url + "/api/blade-workflow/process/todoList-v2?current=1&size=10",
                    HttpMethod.GET, httpEntity, TodoListResultBean.class);
        } catch (RestClientException e) {
            log.error("调用api/blade-workflow/process/todoList-v2出错",e);
           return new TodoListResultBean();

        }
        return exchange.getBody();
    }

    public String getWorkflowUrl() {
        BaseConfig config = baseConfigService.findConfig(Context.getCurrentTenantId(), Context.getCompanyCode(), "workflow.ip.address");
        String url = "";
        if (config == null || StringUtils.isEmpty(config.getValue())) {
            url = "http://127.0.0.1:8886";
        } else {
            url = config.getValue();
        }
        return url;
    }

    @Override
    public List<WorkFlowScreenBean> searchScreenDisplayProcess(String columnCode) {
        List<WorkFlowScreenBean> workFlowScreenBeanList = Lists.newArrayList();

        HttpHeaders headers = getHeaders();
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();
        String code = "";
        if (columnCode != null) {
            code = columnCode;
        }
        ResponseEntity<NewProcessScreenProcessModelResultBean> exchange = null;
        try {
            exchange = restTemplate.exchange(url + "/api/blade-workflow/process/screen/getAllDisplayProcessDefinition?code=" + code,
                    HttpMethod.GET, httpEntity, NewProcessScreenProcessModelResultBean.class);
        } catch (RestClientException e) {
            log.error("调用/api/blade-workflow/process/screen/getAllDisplayProcessDefinition出错", e);
            return workFlowScreenBeanList;

        }
        NewProcessScreenProcessModelResultBean body = exchange.getBody();
        if (body.getCode() == null || body.getCode().intValue() != 200) {
            return workFlowScreenBeanList;
        }
        List<ProcessModelNameBean> data = body.getData();
        if (data == null) {
            return workFlowScreenBeanList;
        }
        data.forEach(record -> {
            WorkFlowScreenBean workFlowScreenBean = new WorkFlowScreenBean();
            workFlowScreenBean.setId("new_" + record.getProcessDefId());
            workFlowScreenBean.setName(record.getName());
            if (StringUtils.isNotEmpty(record.getIconUrl())) {
                try {
                    JSONObject jsonObject = JSONObject.parseObject(record.getIconUrl());
                    if (jsonObject != null) {
                        String fileUrl = jsonObject.getString("fileUrl");
                        workFlowScreenBean.setIconUrl(fileUrl);
                    }
                } catch (Exception e) {
                    log.error("parse file url error fileUrl {} ", record.getIconUrl(), e);
                }
            }
            workFlowScreenBean.setMapSmallScreenEnable(record.getMapSmallScreenEnable());
            workFlowScreenBean.setMapShowName(record.getMapShowName());
            workFlowScreenBean.setMapSmallScreenName(record.getMapSmallScreenName());
            workFlowScreenBeanList.add(workFlowScreenBean);
        });

        return workFlowScreenBeanList;
    }

    @Override
    public List<ProcessMapListBean> searchScreenListWorkFlow(String processId, String serialNumber, String code) {
        List<ProcessMapListBean> result = Lists.newArrayList();
        HttpHeaders headers = getHeaders();
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();

        ResponseEntity<String> exchange = null;
        try {
            String uri = "/api/blade-workflow/process/screen/process/list";
            if (!StringUtils.isEmpty(code)) {
                uri += "?code=" + code;
            } else {
                uri += "?code=";
            }
            if (!StringUtils.isEmpty(processId) && StringUtils.isNotEmpty(serialNumber)) {
                uri += "&processDefId=" + processId + "&serialNumber=" + serialNumber;
            } else if (StringUtils.isNotEmpty(processId)) {
                uri += "&processDefId=" + processId;
            }  else if (StringUtils.isNotEmpty(serialNumber)) {
                uri += "&serialNumber=" + serialNumber;
            }
            log.info("url {} processId {} serialNumber {}", uri, processId, serialNumber);
            exchange = restTemplate.exchange(url + uri,
                    HttpMethod.GET, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("调用/api/blade-workflow/process/screen/process/list出错", e);
            return result;

        }

        String body = exchange.getBody();
        if (body == null) {
            log.info("/api/blade-workflow/process/screen/process/list出错 body {}", body);
            return result;
        }
        try {
            NewProcessScreenListResultBean newProcessScreenListResultBean = JSONUtil.toBean(body, NewProcessScreenListResultBean.class);
            if (newProcessScreenListResultBean != null && newProcessScreenListResultBean.getData() != null) {
                return newProcessScreenListResultBean.getData();
            }
        } catch (Exception e) {
            log.info("查询/api/blade-workflow/process/screen/process/list出错 body {}", body, e);
        }
        log.info("查询/api/blade-workflow/process/screen/process/list出错 body {}", body);

        return result;
    }

    @Override
    public ProcessInstanceMapScreenDetail getProcessInstanceDetail(String processInstanceId) {
        HttpHeaders headers = getHeaders();
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();

        ResponseEntity<String> exchange = null;
        try {
            String uri = "/api/blade-workflow/process/screen/processInstance/detail?processInstanceId=" + processInstanceId;
            exchange = restTemplate.exchange(url + uri,
                    HttpMethod.GET, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("调用/api/blade-workflow/process/screen/processInstance/detail出错", e);
            return new ProcessInstanceMapScreenDetail();

        }

        String body = exchange.getBody();
        if (body == null) {
            log.info("调用/api/blade-workflow/process/screen/processInstance/detail出错", body);
            return new ProcessInstanceMapScreenDetail();
        }

        NewProcessScreenDetailResultBean newProcessScreenDetailResultBean = JSONUtil.toBean(body, NewProcessScreenDetailResultBean.class);
        if (newProcessScreenDetailResultBean == null || newProcessScreenDetailResultBean.getData() == null) {
            return new ProcessInstanceMapScreenDetail();
        }
        return newProcessScreenDetailResultBean.getData();
    }

    @Override
    public ProcessMapListBean getProcDetail(String processInstanceId, BaseUser user) {
        HttpHeaders headers = getHeaders(user);
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();

        ResponseEntity<String> exchange = null;
        try {
            String uri = "/api/blade-workflow/process/procDetail?processInsId=" + processInstanceId;
            exchange = restTemplate.exchange(url + uri,
                    HttpMethod.GET, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("调用/api/blade-workflow/process/procDetail出错", e);
            return new ProcessMapListBean();

        }

        String body = exchange.getBody();
        if (body == null) {
            log.info("调用/api/blade-workflow/process/procDetail出错", body);
            return new ProcessMapListBean();
        }
        Map<String,Object> map = (Map)JSON.parseObject(body).get("data");
        WfProcess process = JSONUtil.toBean(map.get("process").toString(), WfProcess.class);
        if (process == null) {
            return new ProcessMapListBean();
        }
        ProcessMapListBean bean = new ProcessMapListBean();
        bean.setName(process.getProcessDefinitionName());
        bean.setSerialNumber(process.getVariables().get("serialNumber").toString());
        bean.setProcessInstanceId(process.getProcessInstanceId());
        return bean;
    }

    @Override
    public VideoDetailBean getVideoDetail(String processInstanceId, String prop) {
        VideoDetailBean videoDetailBean = new VideoDetailBean();
        HttpHeaders headers = getHeaders();
        headers.set("Accept", "application/json");
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);

        String url = getWorkflowUrl();

        ResponseEntity<String> exchange = null;
        try {
            String uri = "/api/blade-workflow/process/screen/processInstance/video?processInstanceId=" + processInstanceId + "&prop=" + prop;
            exchange = restTemplate.exchange(url + uri,
                    HttpMethod.GET, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("调用/api/blade-workflow/process/screen/processInstance/video出错", e);
            return videoDetailBean;

        }

        String body = exchange.getBody();
        if (body == null) {
            log.info("调用/api/blade-workflow/process/screen/processInstance/video出错", body);
            return videoDetailBean;
        }

        NewProcessVideoDetailResultBean newProcessScreenDetailResultBean = JSONUtil.toBean(body, NewProcessVideoDetailResultBean.class);
        if (newProcessScreenDetailResultBean == null || newProcessScreenDetailResultBean.getData() == null) {
            return videoDetailBean;
        }
        return newProcessScreenDetailResultBean.getData();
    }
}
